package com.xci.sys.service;

import com.github.pagehelper.Page;
import com.xci.core.annotation.Log;
import com.xci.core.annotation.Valid;
import com.xci.core.base.BaseService;
import com.xci.core.internal.Const;
import com.xci.core.base.RestMessage;
import com.xci.core.helper.Helper;
import com.xci.sys.dao.SeqDao;
import com.xci.sys.entity.SysSeq;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.util.List;

/**
 * 序列服务
 */
@Service
public class SeqService extends BaseService {
    @Resource
    private SeqDao seqDao;//序列数据层对象

    /**
     * 新建序列
     * @param entity 序列对象
     */
    @Log(module = Const.Module.Seq, msg = "新建序列")
    @Transactional(rollbackFor = Exception.class)
    public RestMessage insert(@Valid SysSeq entity) {
        return save(entity,true);
    }

    /**
     * 修改序列
     * @param entity 序列对象
     */
    @Log(module = Const.Module.Seq, msg = "修改序列")
    @Transactional(rollbackFor = Exception.class)
    public RestMessage update(@Valid SysSeq entity) {
        return save(entity,false);
    }

    /**
     * 删除序列
     * @param ids 序列主键字符串,多个逗号隔开
     */
    @Log(module = Const.Module.Seq, msg = "删除序列")
    @Transactional(rollbackFor = Exception.class)
    public RestMessage delete(@NotBlank(message = "请指定序列主键字符串") String ids) {
        String[] idList = Helper.splitToArray(ids);
        for(String id : idList) {
            seqDao.delete(id);
        }
        return RestMessage.success();
    }

    /**
     * 检查是否存在指定的序列编码
     * @param code 序列编码
     * @return 如果存在返回true, 否则返回false
     */
    public Boolean existByCode(@NotBlank(message = "请指定序列编码") String code) {
        return seqDao.existByCode(code, null);
    }

    /**
     * 查询当前序列值
     * @param code 序列编码
     */
    public Long selectCurrentValue(@NotBlank(message = "请指定序列编码") String code) {
        return seqDao.currentValue(code);
    }

    /**
     * 查询下一个序列值
     * @param code 序列编码
     */
    @Transactional(rollbackFor = Exception.class)
    public Long selectNextValue(@NotBlank(message = "请指定序列编码") String code) {
        return nextValueCore(code);
    }

    /**
     * 查询单个序列
     * @param id 序列主键
     * @return 返回序列对象
     */
    public SysSeq selectById(@NotBlank(message = "请指定序列主键") String id) {
        return seqDao.selectById(id);
    }

    /**
     * 根据编码查询单个序列
     * @param code 序列编码
     * @return 返回序列对象
     */
    public SysSeq selectByCode(@NotBlank(message = "请指定序列编码") String code) {
        return seqDao.selectByCode(code);
    }

    /**
     * 查询序列列表
     * @param name 编码/名称关键字
     * @return 返回序列对象列表
     */
    public List<SysSeq> selectList(String name) {
        return seqDao.selectList(name);
    }

    /**
     * 查询序列分页列表
     * @param name 编码/名称关键字
     * @return 返回序列对象分页列表
     */
    public Page<SysSeq> selectPageList(String name) {
        return seqDao.selectPageList(name);
    }

    /**
     * 保存序列
     * @param entity 序列对象
     * @param created 是否新建
     */
    private RestMessage save(SysSeq entity, boolean created) {
        //自动添加主键
        if(created && Helper.isBlank(entity.getId())) {
            entity.setId(Helper.nextIdStr());
        }

        //序列编码唯一性验证
        if(seqDao.existByCode(entity.getCode(), created ? null : entity.getId())) {
            String msg = Helper.format("序列编码[{}]已经存在", entity.getCode());
            return RestMessage.fail(msg);
        }

        if(created) {// 新建
            seqDao.insert(entity);
        } else {//修改
            seqDao.update(entity);
        }
        return RestMessage.success();
    }

    /**
     * 获取当前序列值并更新
     * @param code 序列编码
     */
    private Long nextValueCore(String code) {
        Long nextValue = seqDao.currentValue(code);
        if(nextValue == null) {//新建
            nextValue = 1L;
            SysSeq entity = new SysSeq();
            entity.setId(Helper.nextIdStr());
            entity.setName(code);
            entity.setCode(code);
            entity.setStartWith(1L);
            entity.setCurrentValue(nextValue);
            entity.setIncrementBy(1L);
            entity.setRemark("auto");
            seqDao.insert(entity);
        }
        seqDao.incrementValue(code);
        return nextValue;
    }
}